﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp;

namespace MyWatermark
{
    public static class ColorConverter
    {
        // RGB转YUV（BT.601标准）
        public static YuvData RgbToYuv(Image<Bgra32> image)
        {
            int width = image.Width;
            int height = image.Height;
            var yuv = new YuvData
            {
                Y = new double[width, height],
                U = new double[width, height],
                V = new double[width, height],
                Width = width,
                Height = height
            };

            image.ProcessPixelRows(accessor =>
            {
                for (int y = 0; y < height; y++)
                {
                    Span<Bgra32> row = accessor.GetRowSpan(y);
                    for (int x = 0; x < width; x++)
                    {
                        double r = row[x].R / 255.0;
                        double g = row[x].G / 255.0;
                        double b = row[x].B / 255.0;

                        //psnr小，但是比较集中。
                        yuv.Y[x, y] = 0.299 * r + 0.587 * g + 0.114 * b;
                        yuv.U[x, y] = -0.14713 * r - 0.28886 * g + 0.436 * b;
                        yuv.V[x, y] = 0.615 * r - 0.51499 * g - 0.10001 * b;

                        //psnr大，但是分散比较均匀，整体感觉更暗
                        //yuv.Y[x, y] = 0.299 * r + 0.587 * g + 0.114 * b;
                        //yuv.U[x, y] = -0.168736 * r - 0.331264 * g + 0.5 * b;
                        //yuv.V[x, y] = 0.5 * r - 0.418688 * g - 0.081312 * b;
                    }
                }
            });

            return yuv;
        }

        // YUV转RGB（BT.601标准）
        public static Image<Bgra32> YuvToRgb(YuvData yuv)
        {


            var image = new Image<Bgra32>(yuv.Width, yuv.Height);

            image.ProcessPixelRows(accessor =>
            {
                for (int y = 0; y < yuv.Height; y++)
                {
                    Span<Bgra32> row = accessor.GetRowSpan(y);
                    for (int x = 0; x < yuv.Width; x++)
                    {
                        double yVal = yuv.Y[x, y];
                        double uVal = yuv.U[x, y];
                        double vVal = yuv.V[x, y];

                        double r = yVal + 1.13983 * vVal;
                        double g = yVal - 0.39465 * uVal - 0.58060 * vVal;
                        double b = yVal + 2.03211 * uVal;





                        row[x] = new Bgra32(
                            (byte)Math.Clamp((int)Math.Round(r * 255), 0, 255),
                            (byte)Math.Clamp((int)Math.Round(g * 255), 0, 255),
                            (byte)Math.Clamp((int)Math.Round(b * 255), 0, 255),
                            255
                        );
                    }
                }
            });


            return image;
        }
    }

}
